/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "节点编辑.h"
#include "Context/数据创建销毁.h"
#include "Context/虚拟体物体构建.h"


static std::map<S_物体*, S_物体*>	g对称骨骼池;
static std::map<S_物体*, S_骨骼IK*>	g骨骼IK;
static std::vector<S_物体*> g模型拷贝池;
static std::vector<S_物体*> g封套虚拟体;
static std::vector<S_物体*> gIK虚拟体;



void f_node_NED_初始化() {

}
void f_node_NED_清理() {
	for (auto& e : g对称骨骼池) {
		f_ob_销毁(e.first);
	}
	for (auto& e : g模型拷贝池) {
		f_ob_销毁(e);
	}
	for (auto& e : g封套虚拟体) {
		f_ob_销毁(e);
	}
	for (auto& e : gIK虚拟体) {
		f_ob_销毁(e);
	}
	g对称骨骼池.clear();
	g模型拷贝池.clear();
	g封套虚拟体.clear();
	gIK虚拟体.clear();
}



static void f_OE_清除对称物体(S_物体* 物体) {
	uint32 num = 物体->m_子物体.size();

	for (uint32 i = 0; i < num; ++i) {
		f_OE_清除对称物体(static_cast<S_物体*>(物体->m_子物体[i]));
	}

	switch (物体->m_Type) {
		case E_物体类型::t_骨骼: {
			S_骨骼* 骨骼数据 = f_ob_from骨骼(物体);
			
			骨骼数据->m_对称物体 = nullptr;
			骨骼数据->m_对称偏移 = {};
			骨骼数据->m_对称方向 = -1;

			//g对称骨骼池.push_back(物体);
			

			if (骨骼数据->m_IK && 骨骼数据->m_IK->m_末端坐标) {
				g骨骼IK[物体] = 骨骼数据->m_IK;

				gIK虚拟体.push_back(骨骼数据->m_IK->m_末端坐标);
				f_node_物体从主场景中移除(骨骼数据->m_IK->m_末端坐标);
			}
			骨骼数据->m_IK = nullptr;

			break;
		}
		case E_物体类型::t_网格物体:
		case E_物体类型::t_多边形: {
			g模型拷贝池.push_back(物体);
			break;
		}

		case E_物体类型::t_虚拟体: {
			f_node_物体从主场景中移除(物体);
			break;
		}
	}
	
	物体->m_子物体.clear();
}

void f_node_OE_清除对称物体(S_物体* 骨架) {
	uint32 num = 骨架->m_子物体.size();

	for (auto& e : 骨架->m_子物体) {
		f_OE_清除对称物体(static_cast<S_物体*>(e));
	}
}





void f_NE_骨骼物体状态颜色设置(const std::vector<S_物体*>& obs) {
	for (auto& e : obs) {
		auto* 骨架 = static_cast<S_物体*>(e->m_子物体[0]);
		auto* 骨节 = static_cast<S_物体*>(e->m_子物体[1]);

		f_surface_fill颜色(f_ob_getMesh(骨架, 0), S_节点UI主题::uic_骨骼边物体状态, 0, -1);
		f_surface_fill颜色(f_ob_getMesh(骨架, 1), S_节点UI主题::uic_骨骼面物体状态, 0, -1);

		f_surface_fill颜色(f_ob_getMesh(骨节, 0), S_节点UI主题::uic_骨骼边物体状态, 0, -1);
		f_surface_fill颜色(f_ob_getMesh(骨节, 1), S_节点UI主题::uic_骨骼面物体状态, 0, -1);
	}
}

void f_NE_骨骼编辑状态颜色设置(const std::vector<S_物体*>& obs) {
	for (auto& e : obs) {
		auto* 骨架 = static_cast<S_物体*>(e->m_子物体[0]);
		auto* 骨节 = static_cast<S_物体*>(e->m_子物体[1]);

		f_surface_fill颜色(f_ob_getMesh(骨架, 0), S_节点UI主题::uic_骨骼边编辑状态, 0, -1);
		f_surface_fill颜色(f_ob_getMesh(骨架, 1), S_节点UI主题::uic_骨骼面编辑状态, 0, -1);

		f_surface_fill颜色(f_ob_getMesh(骨节, 0), S_节点UI主题::uic_骨骼边编辑状态, 0, -1);
		f_surface_fill颜色(f_ob_getMesh(骨节, 1), S_节点UI主题::uic_骨骼面编辑状态, 0, -1);
	}
}

void f_NE_拷贝物体(const S_OBArray* obs, uint32 拷贝数量, S_OBArray* 新物体组, bool 是否实例, S_设备环境& ctx) {
	uint32 输入组数量 = obs->count;
	uint32 实例总数 = 输入组数量 * 拷贝数量;

	
	for (uint32 j = 0; j < 输入组数量; ++j) {
		auto& 被拷贝的物体 = obs->ptr_userData[j];

		if (是否实例) {
			//新物体组.resize(实例总数);
			f_core_array_resize((S_Array*)新物体组, 实例总数);

			for (uint32 i = 0; i < 拷贝数量; ++i) {
				uint32 offset = 拷贝数量 * j + i;

				//S_物体* 新拷贝物体 = 新物体组[offset];
				S_物体* 新拷贝物体 = 新物体组->ptr_userData[offset];
				if (新拷贝物体 == nullptr) {
					新拷贝物体 = f_NodeCtx_回收物体();
					if (!新拷贝物体) 新拷贝物体 = f_ob_创建(ctx, E_物体类型::t_网格物体);

					新物体组->ptr_userData[offset] = 新拷贝物体;
				}
			
				f_ob_改变物体类型(新拷贝物体, obs->ptr_userData[j]->m_Type);
				f_ob_link物体数据(新拷贝物体, 被拷贝的物体);
				f_ob_set实例数量(新拷贝物体, 拷贝数量);
			
			
				
				S_物体* ob = f_NodeCtx_回收物体();
				if (ob == nullptr) {
					ob = f_ob_创建实例(nullptr, i);
				}
				ob->m_实例ID = i;

				f_ob_add子物体(新拷贝物体, ob, i);
			}

		}
		else {
			//新物体组.resize(实例总数);
			f_core_array_resize((S_Array*)新物体组, 实例总数);

			for (uint32 i = 0; i < 拷贝数量; ++i) {
				auto* 新物体 = f_ob_copy(ctx, 被拷贝的物体);

				uint32 offset = 拷贝数量 * j + i;
				新物体组->ptr_userData[offset] = 新物体;
				新物体组->ptr_userData[offset]->m_Name = u"深度拷贝物体";

			}
		}
	}

}

void f_NE_拷贝物体(const S_OBArray* obs, uint32 拷贝数量, S_物体* 新物体的父物体, S_OBArray* 新物体组, bool 是否实例, S_设备环境& ctx) {
	uint32 输入组数量 = obs->count;
	
	uint32 实例总数 = 输入组数量 * 拷贝数量;
	//新物体组.resize(实例总数);
	f_core_array_resize((S_Array*)新物体组, 实例总数);

	f_ob_clear子物体(新物体的父物体);

	for (uint32 j = 0; j < 输入组数量; ++j) {
		auto* 被拷贝的物体 = obs->ptr_userData[j];

		if (是否实例) {
			S_物体* 新拷贝物体 = f_NodeCtx_回收物体();
			if (!新拷贝物体) 新拷贝物体 = f_ob_创建(ctx, E_物体类型::t_网格物体);
			else f_ob_clear子物体(新物体的父物体);

			if (被拷贝的物体->m_是否实例) {
				被拷贝的物体 = f_ob_get父变换对象(被拷贝的物体);
			}
			

			//f_node_创建网格物体数据()
			f_ob_改变物体类型(新拷贝物体, 被拷贝的物体->m_Type);
			f_ob_link物体数据(新拷贝物体, 被拷贝的物体);
			f_ob_set实例数量(新拷贝物体, 拷贝数量);

			新拷贝物体->m_视口显示模式 = 被拷贝的物体->m_视口显示模式;


			f_node_物体绘制属性设置(新拷贝物体);
			f_mesh_get网格元素绘制属性(f_ob_getMesh(新拷贝物体, E_物体网格元素类型::e_MT_框)).m_TransformMode = DEF_MESH_LINE_TRANFORMTYPEMODEL_CenterZoom;

			switch (被拷贝的物体->m_Type) {
				case E_物体类型::t_包: {
					S_VkDrawIndirectCommand indirect = f_surface_get间接绘制区间(f_ob_getMesh(被拷贝的物体, 0), 0);
					indirect.firstInstance = 0;
					indirect.instanceCount = 拷贝数量;
					f_surface_add间接绘制(f_ob_getMesh(新拷贝物体, 0), indirect);
					break;
				}
			}
			 

			//新拷贝物体->f_打开可视通道(0);
			for (uint32 i = 0; i < 拷贝数量; ++i) {
				uint32 offset = 拷贝数量 * j + i;

				S_物体* ob = f_NodeCtx_回收物体();
				if (ob == nullptr) {
					ob = f_ob_创建实例(nullptr, i);
				}
				else {
					f_ob_改变物体类型(ob, E_物体类型::t_实例);
				}
				ob->m_实例ID = i;
				ob->m_视口显示模式 = 被拷贝的物体->m_视口显示模式;

				新物体组->ptr_userData[offset] = ob;
				f_ob_set实例物体(新拷贝物体, ob, i);



				f_ob_set颜色2(ob, {}, ob->m_实例ID);
				f_ob_set颜色2(ob, S_节点UI主题::uic_模型面, ob->m_实例ID, 1);
				f_ob_set颜色2(ob, S_节点UI主题::uic_模型线, ob->m_实例ID, 2);
				f_ob_set颜色2(ob, S_节点UI主题::uic_模型线, ob->m_实例ID, 3);
			}

			新拷贝物体->m_实例ID = 0;
			新拷贝物体->m_根实例 = true;
			f_ob_add子物体(新物体的父物体, 新拷贝物体, j);
		}
		else {
			
			for (uint32 i = 0; i < 拷贝数量; ++i) {
				uint32 offset = 拷贝数量 * j + i;
				S_物体* 新拷贝物体 = f_ob_copy(ctx, 被拷贝的物体, false);


				新拷贝物体->m_视口显示模式 = 被拷贝的物体->m_视口显示模式;

				新拷贝物体->m_Name = u"复制物体" + f_str_wstring_to_u16(std::to_wstring(i));
				新拷贝物体->m_isUpdate = true;
				新拷贝物体->m_实例ID = 0;
				新拷贝物体->m_根实例 = true;

				新物体组->ptr_userData[offset] = 新拷贝物体;

				f_ob_add子物体(新物体的父物体, 新拷贝物体);
			}
		}
	}
}





static void f_对称变换坐标(const S_Tranform& t1, S_Tranform& t2, bool 对称轴[3], vec3 中心坐标) {
	if (对称轴[0]) {
		t2.position.x = 中心坐标.x - (t1.position.x - 中心坐标.x);
	}
	if (对称轴[1]) {
		t2.position.y = 中心坐标.y - (t1.position.y - 中心坐标.y);
	}
	if (对称轴[2]) {
		t2.position.z = 中心坐标.z - (t1.position.z - 中心坐标.z);
	}
}

S_物体* f_NE_递归复制物体(S_设备环境& ctx, S_物体* ob, uint32 对称轴, const vec3& 中心坐标) {
	S_物体* 新物体 = nullptr;

	switch (ob->m_Type) {
		case E_物体类型::t_骨骼: {
			if (g对称骨骼池.find(ob) != g对称骨骼池.end()) {
				新物体 = g对称骨骼池[ob];
			}
			else {
				新物体 = f_ob_copy(ctx, ob, false);
				g对称骨骼池[ob] = 新物体;
			}
			//if (g对称骨骼池.size()) {
			//	新物体 = g对称骨骼池.back();
			//	g对称骨骼池.pop_back();
			//}
			//else {
			//	新物体 = f_ob_copy(ctx, ob, false);
			//}
			const auto* 源骨骼 = f_ob_from骨骼(ob);
			auto* 骨骼 = f_ob_from骨骼(新物体);

			骨骼->m_对称物体 = ob;
			骨骼->m_对称偏移 = {};
			骨骼->m_对称方向 = 对称轴;

			骨骼->m_封套S内半径 = 源骨骼->m_封套S内半径;
			骨骼->m_封套E内半径 = 源骨骼->m_封套E内半径;
			骨骼->m_封套S外半径 = 源骨骼->m_封套S外半径;
			骨骼->m_封套E外半径 = 源骨骼->m_封套E外半径;
			骨骼->m_自动封套大小 = 源骨骼->m_自动封套大小;


			if (!骨骼->m_封套范围线) {
				
				骨骼->m_封套范围线 = f_node_创建圆柱封套虚拟体(ctx);
				骨骼->m_封套范围线->m_isUpdate = true;
			}

			if (源骨骼->m_IK) {
				if (g骨骼IK.find(新物体) != g骨骼IK.end()) {
					骨骼->m_IK = g骨骼IK[新物体];
					g骨骼IK.erase(新物体);
				}
				else if(!骨骼->m_IK) {
					骨骼->m_IK = f_ob_创建IK();
				}

				f_ob_copyIK(骨骼->m_IK, 源骨骼->m_IK);

				if (!骨骼->m_IK->m_末端坐标) {
					骨骼->m_IK->m_末端坐标 = f_node_create创建十字叉虚拟体(ctx);
				}

				骨骼->m_IK->m_末端 = 新物体;

				f_node_物体添加到主场景(骨骼->m_IK->m_末端坐标);
			}


			break;
		}

		case E_物体类型::t_多边形:
		case E_物体类型::t_网格物体: {
			if (g模型拷贝池.size()) {
				新物体 = g模型拷贝池.back();
				g模型拷贝池.pop_back();
			}
			else {
				goto To_创建新物体;
			}
			break;
		}
		default:
			To_创建新物体:
			新物体 = f_ob_copy(ctx, ob, false);
			新物体->m_可拾取 = false;
			break;
	}
	
	f_NE_对称物体变换(ob, 新物体, 中心坐标, 对称轴);

	
	新物体->m_子物体.clear();

	uint32 num = ob->m_子物体.size();
	for (uint32 i = 0; i < num; ++i) {
		f_ob_add子物体(新物体, f_NE_递归复制物体(ctx, static_cast<S_物体*>(ob->m_子物体[i]), 对称轴, 中心坐标));

	}

	switch (ob->m_Type) {
		case E_物体类型::t_骨骼: {
			auto* 骨骼 = f_ob_from骨骼(新物体);
			f_ob_add子物体(新物体, 骨骼->m_封套范围线);
			break;
		}
	}

	return 新物体;
}

void f_NE_对称物体变换(const S_物体* 源物体, S_物体* 新物体, vec3 中心坐标, uint32 轴) {
	switch (轴) {
		case 0 : {
			新物体->m_变换.position.x = 中心坐标.x + (中心坐标.x - 源物体->m_变换.position.x);
			
			break;
		}
		case 1: {
			新物体->m_变换.position.y = 中心坐标.y + (中心坐标.y - 源物体->m_变换.position.y);

			break;
		}
		case 2: {
			新物体->m_变换.position.z = 中心坐标.z + (中心坐标.z - 源物体->m_变换.position.z);

			break;
		}
	}
}

void f_NE_对称物体(S_设备环境& ctx, const S_OBArray* 源物体, S_OBArray* 新物体, uint32 对称轴位域, vec3 中心坐标) {
	uint32 num = 源物体->count;
	//f_core_array_resize((S_Array*)新物体, num);
	f_core_array_reserve((S_Array*)新物体, 0);

	for (uint32 i = 0; i < num; ++i) {
		std::vector<S_物体*> 以对称物体;

		for (uint32 轴 = 0; 轴 < 3; ++轴) {
			if (对称轴位域 & (1 << 轴)) {
				auto* newOb = f_NE_递归复制物体(ctx, 源物体->ptr_userData[i], 轴, 中心坐标);

				//f_NE_对称物体变换(源物体->ptr_userData[i], newOb, 中心坐标, 轴);
				f_core_array_push_back((S_Array*)新物体, (uint8*)&newOb);

				uint32 已有对称物体数量 = 以对称物体.size();
				for (uint32 k = 0; k < 已有对称物体数量; ++k) {
					auto& se = 以对称物体[k];

					auto* 对称物体 = f_NE_递归复制物体(ctx, se, 轴, 中心坐标);
					//f_NE_对称物体变换(se, 对称物体, 中心坐标, 轴);
					f_core_array_push_back((S_Array*)新物体, (uint8*)&对称物体);
					以对称物体.push_back(对称物体);
				}

				以对称物体.push_back(newOb);
			}
		}
	}
}


void f_NE_多边形转网格(S_物体* Ob, bool 平滑法线) {
	S_多边形* 多边形 = (S_多边形*)Ob->m_UserData;

#pragma omp parallel sections
	{
	#pragma omp section
		{
			uint32 num = 多边形->m_顶点.size();
			std::vector<S_VNT1> 面顶点(num);
			std::vector<S_VC> 顶点(num);
			auto* vert_ptr = 面顶点.data();
			for (uint32 i = 0; i < num; ++i) {
				顶点[i].vert = vert_ptr[i].vert = 多边形->m_顶点[i];
				顶点[i].color = f_PackData4X8({ 127,127,0,255 });

				vert_ptr[i].normal = {};
				vert_ptr[i].UV = {};
			}
			auto* 点网格 = f_ob_getMesh(Ob, 2);
			f_mesh_fill顶点数据(点网格, 顶点);


			num = 多边形->m_面.size();
			if (num) {
				auto* 面 = f_ob_getMesh(Ob, 1);
				f_mesh_fill顶点数据(面, 面顶点);
				f_mesh_多边形三角化(面, 多边形);

				auto mat = f_mat44_identity();

				if (平滑法线) {
					f_surface_计算面平滑法线(面);
				}
			}

			f_mesh_计算包围盒(f_ob_getMesh(Ob, E_物体网格元素类型::e_MT_面));
		}
	#pragma omp section
		{
			uint32 边数量 = 多边形->m_边_过时成员.size();
			std::vector<S_VC> 顶点边;
			顶点边.reserve(边数量 * 2);
			for (uint32 i = 0; i < 边数量; ++i) {
				uint32 边数量 = 多边形->m_边_过时成员[i]->edge.size();

				auto edge = 多边形->m_边_过时成员[i]->edge.data();
				for (uint32 j = 0; j < 边数量; ++j) {
					uint32 id = i * 边数量 + j;
					S_VC v;
					v.vert = 多边形->m_顶点[edge[j].x];
					v.color = f_PackData4X8({ 0,0,0,255 });
					顶点边.push_back(v);

					v.vert = 多边形->m_顶点[edge[j].y];
					v.color = f_PackData4X8({ 0,0,0,255 });
					顶点边.push_back(v);
				}
			}
			auto* 线 = f_ob_getMesh(Ob, 3);
			f_mesh_fill顶点数据(线, 顶点边);
		}
	}

	f_scene_更新物体渲染(f_NodeCtx_get默认场景(), Ob);

}








static std::map<S_物体*, S_可编辑物体*> g可编辑物体容器;

S_可编辑物体* f_OE_创建可编辑物体属性(S_物体* ob) {
	S_可编辑物体* eo;
	if (g可编辑物体容器.find(ob) != g可编辑物体容器.end()) {
		uint32 size = sizeof(S_可编辑物体);
		eo = new S_可编辑物体;
		eo->m_Ob = ob;

		eo->m_当前激活UV层 = f_alloc_UI32FlagBitsProp(nullptr, u"激活UV层");
		eo->m_当前激活UV层.m_私有 = true;
		f_prop_UI32(eo->m_当前激活UV层) = 1;

		g可编辑物体容器[ob] = eo;
	}
	else {
		eo = g可编辑物体容器[ob];
	}

	return eo;
}

S_可编辑物体* f_OE_取可编辑物体属性(S_物体* ob) {
	if (g可编辑物体容器.find(ob) != g可编辑物体容器.end()) {
		return g可编辑物体容器[ob];
	}
	return nullptr;
}

void f_OE_销毁可编辑物体属性(S_物体* ob) {
	if (g可编辑物体容器.find(ob) != g可编辑物体容器.end()) {
		delete (g可编辑物体容器[ob]);

		g可编辑物体容器.erase(ob);
	}
}

void f_OE_销毁所有可编辑物体属性() {
	for (auto& e : g可编辑物体容器) {
		delete (e.second);
	}

	g可编辑物体容器.clear();
}







static void f_更新骨骼封套范围线绘制(S_物体* ob) {
	auto* 骨骼 = f_ob_from骨骼(ob);

	if (骨骼->m_封套范围线) {
		auto& et0 = f_mesh_get网格元素绘制属性(f_ob_getMesh(骨骼->m_封套范围线, 0));
		et0.m_XScale = et0.m_YScale = et0.m_ZScale = 骨骼->m_封套S内半径;
		et0.m_ZScale = -et0.m_ZScale;
		et0.m_TransformMode = DEF_MESH_LINE_TRANFORMTYPEMODEL_CenterZoom;

		auto& et1 = f_mesh_get网格元素绘制属性(f_ob_getMesh(骨骼->m_封套范围线, 1));
		et1.m_XScale = et1.m_YScale = et1.m_ZScale = 骨骼->m_封套E内半径;
		et1.m_ZMove = 骨骼->m_长度;
		et1.m_TransformMode = DEF_MESH_LINE_TRANFORMTYPEMODEL_CenterZoom;


		auto& et2 = f_mesh_get网格元素绘制属性(f_ob_getMesh(骨骼->m_封套范围线, 2));
		et2.m_XScale = et2.m_YScale = et2.m_ZScale = 骨骼->m_封套S外半径;
		et2.m_ZScale = -et2.m_ZScale;
		et2.m_TransformMode = DEF_MESH_LINE_TRANFORMTYPEMODEL_CenterZoom;

		auto& et3 = f_mesh_get网格元素绘制属性(f_ob_getMesh(骨骼->m_封套范围线, 3));
		et3.m_XScale = et3.m_YScale = et3.m_ZScale = 骨骼->m_封套E外半径;
		et3.m_ZMove = 骨骼->m_长度;
		et3.m_TransformMode = DEF_MESH_LINE_TRANFORMTYPEMODEL_CenterZoom;



		f_ob_set颜色2(骨骼->m_封套范围线, { 255,0,0,255 }, 0, 0);
		f_ob_set颜色2(骨骼->m_封套范围线, { 255,0,0,255 }, 0, 1);
		f_ob_set颜色2(骨骼->m_封套范围线, { 0,0,255,255 }, 0, 2);
		f_ob_set颜色2(骨骼->m_封套范围线, { 0,0,255,255 }, 0, 3);

		f_ob_set颜色2(骨骼->m_封套范围线, { 255,0,0,255 }, 0, 4);
		//f_ob_set颜色2(m_封套, { 0,0,255,255 }, 0, 5);

		f_ob_getMesh(骨骼->m_封套范围线, 0)->m_Color = { 255,0,0,255 };
		f_ob_getMesh(骨骼->m_封套范围线, 1)->m_Color = { 255,0,0,255 };
		f_ob_getMesh(骨骼->m_封套范围线, 2)->m_Color = { 0,0,255,255 };
		f_ob_getMesh(骨骼->m_封套范围线, 3)->m_Color = { 0,0,255,255 };

		f_ob_getMesh(骨骼->m_封套范围线, 4)->m_Color = { 255,0,0,255 };


		auto 桶网格 = f_ob_getMesh(骨骼->m_封套范围线, 4);
		auto& et4 = f_mesh_get网格元素绘制属性(桶网格);
		桶网格->m_片源着色模式 = DEF_DrawType_Normal_To_Col;

		static std::vector<S_VNT1> 顶点{
			{ {1, 0, 0}, {1,0,0}, {} },
			{ {0, 1, 0}, {1,0,0}, {} },
			{ {-1, 0, 0}, {0,0,1}, {} },
			{ {0, -1, 0}, {0,0,1}, {} },

		};

		auto* vert = f_buf_VNT_ptr(*桶网格->m_顶点);
		for (uint32 i = 0; i < 4; ++i) {
			vert[i].vert = 顶点[i].vert * 骨骼->m_封套S内半径;
			vert[i + 4].vert = 顶点[i].vert * 骨骼->m_封套E内半径;
			vert[i + 4].vert.z = 骨骼->m_长度;

			vert[i + 8].vert = 顶点[i].vert * 骨骼->m_封套S外半径;
			vert[i + 12].vert = 顶点[i].vert * 骨骼->m_封套E外半径;
			vert[i + 12].vert.z = 骨骼->m_长度;
		}

		骨骼->m_封套范围线->m_isUpdate = true;
	}


	for (auto& e : ob->m_子物体) {
		if (static_cast<S_物体*>(e)->m_Type == E_物体类型::t_骨骼) {
			f_更新骨骼封套范围线绘制(static_cast<S_物体*>(e));
		}
	}
}

void f_OE_更新骨骼封套范围线绘制(S_物体* ob) {
	for (auto& e : ob->m_子物体) {
		if (static_cast<S_物体*>(e)->m_Type == E_物体类型::t_骨骼) {
			f_更新骨骼封套范围线绘制(static_cast<S_物体*>(e));
		}
	}
}

void f_OE_网格自定义属性和面材质设置(S_Mesh* me, S_材质管线* 材质, uint8 槽, uint32 光追材质ID) {
	uint32 面数量 = me->m_面->m_Mem.m_数量;
	if (!面数量) return;

	auto* 材质槽ID = me->m_材质槽ID->ptr_userData;
	bool 槽多例 = me->m_材质槽ID->count >= 面数量;

	S_FaceElement* fe = f_buf_面元素_ptr(*me->m_面);
	for (uint32 f = 0; f < 面数量; ++f) {
		if (槽多例) {
			if (材质槽ID[f] == 槽) fe[f].MaterialID = 光追材质ID;
		}
		else {
			if (材质槽ID[0] == 槽) fe[f].MaterialID = 光追材质ID;
		}
	}


	auto& 网格自定义属性索引 = *me->m_自定义属性索引;
	if (材质->m_网格自定义属性布局.size()) {
		for (auto& 材质链接网格自定义属性 : 材质->m_网格自定义属性布局) {
			S_CustomAttr a{};

			switch (材质链接网格自定义属性.m_分布方式) {
				case DEF_ShaderAttrLayout_Point: {
					auto& attr = *me->m_点自定义属性区间偏移;
					if (attr.find(*材质链接网格自定义属性.m_Name) != attr.end()) {

						a.offset = attr[*材质链接网格自定义属性.m_Name].m_Mem.m_偏移;
						a.num = attr[*材质链接网格自定义属性.m_Name].m_Mem.m_数量;

						f_buf_属性索引_at(网格自定义属性索引, 槽 * DEF_网格自定义属性槽数量 + 材质链接网格自定义属性.m_OffsetID) = a;
					}
					break;
				}

				case DEF_ShaderAttrLayout_Face: {
					auto& attr = *me->m_面自定义属性区间偏移;
					if (attr.find(*材质链接网格自定义属性.m_Name) != attr.end()) {
						a.offset = attr[*材质链接网格自定义属性.m_Name].m_Mem.m_偏移;
						a.num = attr[*材质链接网格自定义属性.m_Name].m_Mem.m_数量;

						f_buf_属性索引_at(网格自定义属性索引, 槽 * DEF_网格自定义属性槽数量 + 材质链接网格自定义属性.m_OffsetID) = a;
					}
					break;
				}
			}
		}
	}
	else {
		for (uint32 自定义属性槽ID = 0; 自定义属性槽ID < DEF_网格自定义属性槽数量; ++自定义属性槽ID) {
			f_buf_属性索引_at(网格自定义属性索引, 槽 * DEF_网格自定义属性槽数量 + 自定义属性槽ID) = {};
		}
	}
}









void f_OE_更新世界渲染空间物体() {
	for (auto& e : S_节点数据::g_渲染世界数据) {
		for (auto& 层 : e.second->m_子物体) {
			f_ob_构建底层层光追加速结构((S_渲染对象**)层->m_子物体.data(), 层->m_子物体.size());
		}
	}


	for (auto& e : S_节点数据::g_渲染世界数据) {
		S_渲染世界* 世界 = (S_渲染世界*)e.second->m_UserData;

		uint32 num = e.second->m_子物体.size();
		f_bm_resize(世界->m_物体指针, num);
		世界->m_层.resize(num);


		for (auto& 层 : e.second->m_子物体) {
			S_渲染层* 渲染层 = ((S_渲染层*)(层->m_UserData));
			f_ob_构建顶层光追加速结构(渲染层, (S_渲染对象**)层->m_子物体.data(), 层->m_子物体.size());
		}
	}


	for (auto& e : S_节点数据::g_渲染世界数据) {
		S_渲染世界* 世界 = (S_渲染世界*)e.second->m_UserData;

		uint32 num = e.second->m_子物体.size();
		for (uint32 i = 0; i < num; ++i) {
			S_渲染层* 渲染层 = ((S_渲染层*)(e.second->m_子物体[i]->m_UserData));
			f_bm_at<uint64>(世界->m_物体指针, i) = f_buf_getAddress2(渲染层->m_光追实例物体);

			世界->m_层[i] = 渲染层;
		}

		f_ob_光追加速结构描述集(世界);
	}

}

void f_OE_更新渲染物体变换() {
	for (auto& e : S_节点数据::g_渲染世界数据) {
		S_渲染世界* 世界 = (S_渲染世界*)e.second->m_UserData;

		uint32 num = e.second->m_子物体.size();
		for (uint32 i = 0; i < num; ++i) {
			S_渲染层* 渲染层 = ((S_渲染层*)(e.second->m_子物体[i]->m_UserData));
			f_bm_at<uint64>(世界->m_物体指针, i) = f_buf_getAddress2(渲染层->m_光追实例物体);

			世界->m_层[i] = 渲染层;
		}

		f_ob_光追加速结构描述集(世界);
	}
}







